/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Description: Hmfs-tools command
 */

#include "hmfs_command.h"

#include <cstdio>
#include <cstdlib>
#include <getopt.h>
#include <sstream>
#include <string>

#include "hmfs_common.h"
#include "hmfs_encoding.h"
#include "hmfs_fs.h"
#include "hmfs_log.h"

namespace OHOS {
namespace Hmfs {
CmdParser *CmdParser::instance_ = nullptr;
void CmdParser::RegCmdOption(char option, bool hasPara, HandleArgValue handle)
{
    optionString_ += option;
    if (hasPara) {
        optionString_ += ':';
    }
    handles_.emplace(option, handle);
}

ArgParseResult CmdParser::ParseOption(int32_t argc, char *argv[])
{
    const struct option longOptions[] = {
        {"help", no_argument, nullptr, 'h'},
        {nullptr, 0, nullptr, 0}
    };

    int32_t ret = -1;
    while ((ret = getopt_long(argc, argv, optionString_.c_str(), longOptions, nullptr)) != EOF) {
        char option = static_cast<char>(ret);
        std::string argValue = (optarg != nullptr) ? optarg : "";
        ArgParseResult result = ProcessOption(option, argValue);
        if (result != ArgParseResult::OK) {
            if (result != ArgParseResult::FINISH) {
                ShowCmdUsage();
            }
            return result;
        }
    }

    return ArgParseResult::OK;
}

ArgParseResult CmdParser::ProcessOption(char option, const std::string &argValue)
{
    auto handler = handles_.find(option);
    if (handler == handles_.end()) {
        HMFS_ERROR("Unknown option '%c'", option);
        return ArgParseResult::ERROR;
    }
    return handler->second(argValue);
}

ArgParseResult CmdParser::ProcessCasefolding(const std::string &argValue)
{
    std::stringstream input(argValue);
    std::string encodingStr;
    std::getline(input, encodingStr, ':');
    if (EncodingStrToValue(encodingStr, cfgPara_.sEncoding)) {
        HMFS_ERROR("Unknown encoding : %s", encodingStr.c_str());
        return ArgParseResult::ERROR;
    }

    std::string flagStr;
    if (std::getline(input, flagStr, ':')) {
        if (EncodingFlagStrToValue(flagStr, cfgPara_.sEncodingFlags)) {
            HMFS_ERROR("Unknown flag : %s", flagStr.c_str());
            return ArgParseResult::ERROR;
        }
    } else {
        cfgPara_.sEncodingFlags = GetDefaultEncodingFlag(cfgPara_.sEncoding);
    }

    cfgPara_.features |= HMFS_FEATURE_CASEFOLD;
    return ArgParseResult::OK;
}

ArgParseResult CmdParser::ProcessDebugLevel(const std::string &argValue)
{
    cfgPara_.debugLevel = atoi(argValue.c_str());
    return ArgParseResult::OK;
}

ArgParseResult CmdParser::ProcessFeatures(const std::string &argValue)
{
    std::unordered_map<std::string, uint32_t> featureTable = {
        {"encrypt",                HMFS_FEATURE_ENCRYPT},
        {"extra_attr",             HMFS_FEATURE_EXTRA_ATTR},
        {"project_quota",          HMFS_FEATURE_PRJQUOTA},
        {"inode_checksum",         HMFS_FEATURE_INODE_CHKSUM},
        {"flexible_inline_xattr",  HMFS_FEATURE_FLEXIBLE_INLINE_XATTR},
        {"quota",                  HMFS_FEATURE_QUOTA_INO},
        {"inode_crtime",           HMFS_FEATURE_INODE_CRTIME},
        {"lost_found",             HMFS_FEATURE_LOST_FOUND},
        {"verity",                 HMFS_FEATURE_VERITY},
        {"sb_checksum",            HMFS_FEATURE_SB_CHKSUM},
        {"casefold",               HMFS_FEATURE_CASEFOLD},
        {"compression",            HMFS_FEATURE_COMPRESSION},
        {"ro",                     HMFS_FEATURE_RO},
    };

    std::vector<std::string> featureList = HmfsCommon::GetInstance().SplitStringList(argValue, ',');
    for (auto &feature : featureList) {
        HMFS_DEBUG("-O featureTrim: %s", feature.c_str());
        auto it = featureTable.find(feature);
        if (it == featureTable.end()) {
            HMFS_ERROR("Wrong features: %s", feature.c_str());
            return ArgParseResult::ERROR;
        }
        cfgPara_.features |= it->second;
    }
    return ArgParseResult::OK;
}

ArgParseResult CmdParser::ProcessOverProvision(const std::string &argValue)
{
    cfgPara_.overProvision = atof(argValue.c_str());
    return ArgParseResult::OK;
}

ArgParseResult CmdParser::ProcessLargeNatBitmap(const std::string &argValue)
{
    (void)argValue;
    cfgPara_.largeNatBitmap = 1;
    return ArgParseResult::OK;
}

} // namespace Hmfs
} // namespace OHOS